#pragma  once
#include "pde_export.h"
#include <vector>
#include <memory>
#include <string>
#include "glm/vec3.hpp"
#include "glm/vec4.hpp"
#include "pdeDoseModel.h"

namespace pde {

	//-----------------------------------------------------------------------------
	class pde_export OptFunc {
	public:
		static std::shared_ptr<OptFunc> New();
		OptFunc();
		~OptFunc();

		std::string to_bson();
		bool from_bson(const std::string& bson_str);

		
		SetGetMacro(int, roi_number);
		SetGetMacro(int, roi_type);
		SetGetMacro(int, func_type);
		SetGetMacro(int, rbe_dose); //0: phy dose, 1: rbe dose
		SetGetMacro(double, weight);
		SetGetMacro(double, volume);
		SetGetMacro(double, dose);

	};
	
	//-----------------------------------------------------------------------------
	class pde_export Spot {
	public:
		static std::shared_ptr<Spot> New();
		Spot();
		~Spot();

		void set_position(double x, double y, double z);
		std::string to_bson();
		bool from_bson(const std::string& bson_str);

		SetGetMacro(glm::dvec3, position);
		SetGetMacro(double, mu);
		SetGetMacro(std::shared_ptr<DoseModel>, dose_model);
	};
	//-----------------------------------------------------------------------------
	class pde_export Layer {
	public:
		static std::shared_ptr<Layer> New();
		Layer();
		~Layer();

		std::string to_bson();
		bool from_bson(const std::string& bson_str);

		SetGetMacro(double, range_shift);
		SetGetMacro(double, energy);
		SetGetMacro(std::vector<std::shared_ptr<Spot>>, spot_list);

	};

	//-----------------------------------------------------------------------------
	class pde_export Beam {
	public:
		static std::shared_ptr<Beam> New();
		Beam();
		~Beam();

		std::string to_bson();
		bool from_bson(const std::string& bson_str);

		SetGetMacro(glm::dvec3, iso_center);
		SetGetMacro(double, gantry_angle);
		SetGetMacro(double, couch_angle);
		SetGetMacro(double, weight);
		SetGetMacro(int, nozzle_id);
		SetGetMacro(std::vector<std::shared_ptr<Layer>>, layer_list);
		SetGetMacro(glm::dvec2, snout_innter_range);
		SetGetMacro(double, snout_tip_distance_to_iso);
	};

	//-----------------------------------------------------------------------------
	class pde_export Plan {
	public:
		static std::shared_ptr<Plan> New();
		Plan();
		~Plan();

		std::string to_bson();
		bool from_bson(const std::string& bson_str);

		bool to_file(const std::string& fn);
		bool from_file(const std::string& fn);

		bool load_dose_models(std::shared_ptr<Nozzle> nozzle);



	private:
		SetGetMacro(std::vector<std::shared_ptr<Beam>>, beam_list);
		SetGetMacro(std::vector<std::shared_ptr<OptFunc>>, opt_func_list);


		SetGetMacro(glm::dvec4, beam_margins);//bev projection margins for x1,x2,y1,y2, in mm
		SetGetMacro(int, repaint_count);//optimize parameter
		SetGetMacro(int, robust_opt);//flag indicates if or not use robust optimization
		SetGetMacro(double, robust_tol); //optimization tolerance
		SetGetMacro(int, opt_max_iter_count);//optimization maximum iteration count
		SetGetMacro(int, opt_limit_time);//optimization maximum allowed running time in second

	};

}